import { useState, useRef, useEffect } from 'react'
import { useThree } from '@react-three/fiber'
import { Vector3, Plane, type Object3D } from 'three'

interface UseDragModelOptions {
  /** 模型引用 */
  modelRef: React.RefObject<Object3D>
  /** 拖拽开始 */
  onDragStart?: () => void
  /** 拖拽结束 */
  onDragEnd?: () => void
}

/**
 * 模型拖拽 
 * 
 */
export function useDragModel({ modelRef, onDragStart, onDragEnd }: UseDragModelOptions) {
  const { raycaster, camera, gl } = useThree()
  const [isDragging, setIsDragging] = useState(false)
  const dragPlaneRef = useRef<Plane | null>(null)
  const dragStartPosRef = useRef<Vector3>(new Vector3())
  const dragStartModelPosRef = useRef<Vector3>(new Vector3())


  const onDragEndRef = useRef(onDragEnd)
  useEffect(() => {
    onDragEndRef.current = onDragEnd
  }, [onDragEnd])

  // 拖拽移动
  useEffect(() => {
    if (!isDragging) return

    const handlePointerMove = (event: PointerEvent) => {
      //阻止默认行为，防止触发three.js的鼠标事件
      event.stopPropagation()
      event.preventDefault()
      
      if (!modelRef.current || !dragPlaneRef.current) return

      // 计算鼠标在拖拽平面上的位置
      const x = (event.clientX / gl.domElement.clientWidth) * 2 - 1
      const y = 1 - (event.clientY / gl.domElement.clientHeight) * 2
      raycaster.setFromCamera({ x, y }, camera)

      const intersection = new Vector3()
      raycaster.ray.intersectPlane(dragPlaneRef.current, intersection)

      if (intersection) {
        const offset = intersection.sub(dragStartPosRef.current)
        modelRef.current.position.copy(dragStartModelPosRef.current).add(offset)
      }
    }

    const handlePointerUp = () => {
      setIsDragging(false)
      onDragEndRef.current?.()
    }

    gl.domElement.addEventListener('pointermove', handlePointerMove, { passive: false })
    gl.domElement.addEventListener('pointerup', handlePointerUp)

    return () => {
      gl.domElement.removeEventListener('pointermove', handlePointerMove)
      gl.domElement.removeEventListener('pointerup', handlePointerUp)
    }
  }, [isDragging, camera, raycaster, gl, modelRef])

  const handlePointerDown = (event: React.PointerEvent & { point?: Vector3 }) => {

    event.stopPropagation()
    event.preventDefault?.()
    
   
    onDragStart?.()

    if (!modelRef.current) return

    setIsDragging(true)

    // 计算拖拽平面
    const planeNormal = new Vector3()
    camera.getWorldDirection(planeNormal)
    const modelPos = modelRef.current.position.clone()
    //创建平面
    dragPlaneRef.current = new Plane(planeNormal.clone().negate(), -planeNormal.dot(modelPos))

    // 记录起始位置
    const point = event.point
    dragStartPosRef.current.copy(point || modelPos)
    dragStartModelPosRef.current.copy(modelPos)
  }

  return {
    isDragging,
    dragProps: {
      onPointerDown: handlePointerDown,
      onPointerOver: () => !isDragging && (document.body.style.cursor = 'grab'),
      onPointerOut: () => !isDragging && (document.body.style.cursor = 'default'),
    },
  }
}
